package flc.ast.utils;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FileScannerUtils {
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private final Handler mainHandler = new Handler(Looper.getMainLooper());
    
    public interface ScanCallback {
        void onDuplicateFound(Map<String, List<File>> duplicates);
        void onLargeFilesFound(List<File> largeFiles);
        void onProgressUpdate(int progress);
        void onError(String message);
    }

    public void scanFiles(Context context, long sizeThreshold, ScanCallback callback) {
        executor.execute(() -> {
            try {
                File root = Environment.getExternalStorageDirectory();
                Map<String, List<File>> duplicates = new HashMap<>();
                List<File> largeFiles = new ArrayList<>();
                
                scanDirectory(root, sizeThreshold, duplicates, largeFiles, callback);
                
                mainHandler.post(() -> {
                    callback.onDuplicateFound(duplicates);
                    callback.onLargeFilesFound(largeFiles);
                });
            } catch (Exception e) {
                mainHandler.post(() -> callback.onError(e.getMessage()));
            }
        });
    }

    private void scanDirectory(File dir, long threshold, 
            Map<String, List<File>> duplicates, 
            List<File> largeFiles,
            ScanCallback callback) {
        File[] files = dir.listFiles();
        if (files == null) return;

        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            if (file.isDirectory()) {
                scanDirectory(file, threshold, duplicates, largeFiles, callback);
            } else {
                processFile(file, threshold, duplicates, largeFiles);
            }
            updateProgress(i, files.length, callback);
        }
    }

    private void processFile(File file, long threshold, 
            Map<String, List<File>> duplicates, 
            List<File> largeFiles) {
        // Large file detection
        if (file.length() > threshold) {
            largeFiles.add(file);
        }

        // Duplicate detection
        try {
            String hash = calculateFileHash(file);
            if (!duplicates.containsKey(hash)) {
                duplicates.put(hash, new ArrayList<>());
            }
            duplicates.get(hash).add(file);
        } catch (Exception ignored) {}
    }

    private String calculateFileHash(File file) throws IOException, NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                digest.update(buffer, 0, bytesRead);
            }
        }
        return bytesToHex(digest.digest());
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    private void updateProgress(int current, int total, ScanCallback callback) {
        int progress = (int) ((current / (float) total) * 100);
        mainHandler.post(() -> callback.onProgressUpdate(progress));
    }

    public void shutdown() {
        executor.shutdownNow();
    }
}
